﻿using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using Framework.Core;
using Framework.Remoting.Conventions;
using Framework.Remoting.Hosting;
using ProtoBuf.ServiceModel;
using Rhino.Mocks;
using Xunit;

namespace Framework.Tests.Wcf.Hosting
{
    public class ServiceHostFactoryTestable : ServiceHostFactory
    {
        public int HostClosedTimes;
        public int HostOpenedTimes;

        public ServiceHostFactoryTestable(IWcfServiceInfoFactory wcfServiceInfoFactory)
            : base(wcfServiceInfoFactory)
        {
        }

        protected override void OnHostOpened(Type contractType, Type serviceType, Uri baseAddress)
        {
            HostOpenedTimes++;
            base.OnHostOpened(contractType, serviceType, baseAddress);
        }

        protected override void OnHostClosed(Type contractType)
        {
            HostClosedTimes++;
            base.OnHostClosed(contractType);
        }
    }

    public class IoCServiceHostFactoryTest
    {
        private readonly ServiceHostFactoryTestable target;
        private readonly MockRepository mockRepository = new MockRepository();
        private readonly IWcfServiceInfoFactory wcfServiceInfoFactoryMock;

        public IoCServiceHostFactoryTest()
        {
            wcfServiceInfoFactoryMock = mockRepository.StrictMock<IWcfServiceInfoFactory>();
            target = new ServiceHostFactoryTestable(wcfServiceInfoFactoryMock);
        }

        [Fact]
        public void Test_Create_Close_Succeed()
        {
            wcfServiceInfoFactoryMock
                .Expect(x => x.Create(EnvMode.Dev, typeof(IDummyContract)))
                .Return(new WcfServiceInfo(new NetTcpBinding(), new Uri("net.tcp://localhost:10301/Dev/Pouet")));

            mockRepository.ReplayAll();

            var host = target.Create(typeof(Contract), EnvMode.Dev);
            try
            {
                Assert.True(host.State == CommunicationState.Opened);

                Assert.False(
                    host.Description.Behaviors.Find<ServiceDebugBehavior>().IncludeExceptionDetailInFaults);
                // ReSharper disable PossibleNullReferenceException
                Assert.NotNull(
                    host.Description.Endpoints.Find(typeof(IDummyContract)).Behaviors.Find
                        <ProtoEndpointBehavior>());
                // ReSharper restore PossibleNullReferenceException
            }

            finally
            {
                target.Close(host);
                Assert.True(host.State == CommunicationState.Closed);
            }
            mockRepository.VerifyAll();

            Assert.Equal(1, target.HostOpenedTimes);
            Assert.Equal(1, target.HostClosedTimes);
        }
    }
}